package cn.thoughtworks.school.services;


import cn.thoughtworks.school.entities.HomeworkQuiz;
import cn.thoughtworks.school.entities.Tag;
import cn.thoughtworks.school.entities.User;
import cn.thoughtworks.school.entities.dto.AssignmentQuizData;
import cn.thoughtworks.school.handlers.BusinessException;
import cn.thoughtworks.school.repositories.HomeworkQuizRepository;
import cn.thoughtworks.school.requestParams.CreateHomeworkParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class HomeworkQuizService {
    @Autowired
    private HomeworkQuizRepository homeworkQuizRepository;
    @Autowired
    private Utils utils;
    @Autowired
    private UserCenterService userCenterService;
    @Autowired
    private QuizService quizService;
    @Value("${quiz-center-url}")
    private String quizCenterUrl;
    @Value("${homework-type}")
    private String type;
    @Value("${homework-quiz-jenkins-url.add}")
    private String addHomeworkQuizJenkinsUrl;
    private String githubToken = "ca56d5b5467bc58ed784d14483bc233e87291fd0";
    public HomeworkQuiz getHomeworkQuiz(Long id) throws BusinessException {
        return homeworkQuizRepository.findById(id).orElseThrow(() -> {
            String message = String.format("HomeworkQuiz is not exist with id: %s", id);
            return new BusinessException(message);
        });
    }

  public HomeworkQuiz createHomework(CreateHomeworkParam createHomeworkParam, User user) {
      Long organizationId = userCenterService.getUserCurrentOrganizationId(user.getId());
      HomeworkQuiz homeworkQuiz = new HomeworkQuiz();
      homeworkQuiz.setOrganizationId(organizationId);
      homeworkQuiz.setTemplateRepository("生成中");
      homeworkQuiz.setMakerId(user.getId());
      homeworkQuiz.setTags(utils.formatTags(createHomeworkParam.getTags(), user.getId()));
      homeworkQuiz.setDefinitionRepo(createHomeworkParam.getDefinitionRepo());
      homeworkQuiz.setHomeworkName(createHomeworkParam.getTitle());
      homeworkQuiz.setStackId(createHomeworkParam.getStackId());
      homeworkQuiz.setAvailable(true);
      homeworkQuiz.setRemark(createHomeworkParam.getRemark());
      homeworkQuiz = homeworkQuizRepository.save(homeworkQuiz);

      RestTemplate template = new RestTemplate();

      String callbackUrl = quizCenterUrl + "/api/v3/homeworkQuizzes/" + homeworkQuiz.getId() + "/status";

      MultiValueMap data = new LinkedMultiValueMap();
      data.add("github_token", githubToken);
      data.add("git", homeworkQuiz.getDefinitionRepo());
      data.add("callback_url", callbackUrl);

      template.postForObject(addHomeworkQuizJenkinsUrl, data, String.class);

      return homeworkQuiz;
    }

    public Page getHomeQuizzesPageable(Pageable pageable, Long id, Long userId, String description, List<String> tags, User user) {
      Long currentOrganizationId = userCenterService.getUserCurrentOrganizationId(user.getId());
      List<Long> quizIds = getQuizIdsByTags(tags);
      Page<HomeworkQuiz> homeworkQuizPage = getHomeworkQuizPage(currentOrganizationId, pageable, id, userId, description, quizIds);

      return utils.format(homeworkQuizPage, pageable);
    }

    private Page<HomeworkQuiz> getHomeworkQuizPage(Long organizationId, Pageable pageable, Long id, Long userId, String description, List<Long> quizIds) {
      return homeworkQuizRepository.findAll((Specification<HomeworkQuiz>) (root, query, criteriaBuilder) -> {
        List<Predicate> predicates = quizService.getDefaultPredicates(organizationId, id, userId, description, quizIds, root, criteriaBuilder);
        return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
      }, pageable);
    }


    private List<Long> getQuizIdsByTags(List<String> tags) {
      List<HomeworkQuiz> quizzes = homeworkQuizRepository.findHomeworkQuizzesByTags(tags);
      if (Objects.nonNull(tags) && quizzes.isEmpty()) {
        return Arrays.asList(-1L);
      }
      return quizzes.stream().map(HomeworkQuiz::getId).collect(Collectors.toList());
   }

  public List<AssignmentQuizData> copy(List<AssignmentQuizData> homeworkQuizzesData) {
    List<Long> ids = homeworkQuizzesData.stream().map(AssignmentQuizData::getQuizId).collect(Collectors.toList());
    List<HomeworkQuiz> homeworkQuizzes = homeworkQuizRepository.findByIdIn(ids);

    homeworkQuizzesData.forEach(quizData -> {
      Long creatorId = quizData.getCreatorId();
      HomeworkQuiz homeworkQuiz = homeworkQuizzes.stream()
        .filter(quiz -> quiz.getId().equals(quizData.getQuizId()))
        .findFirst().get();
      Set<Tag> tags = quizService.copyTags(quizData.getOrganizationId(), homeworkQuiz.getTags(), creatorId);
      Long stackId = quizService.copyStack(quizData.getOrganizationId(), homeworkQuiz.getStackId(), creatorId);
      homeworkQuiz = HomeworkQuiz.copy(homeworkQuiz, creatorId, quizData.getOrganizationId(),tags,stackId);
      homeworkQuizRepository.save(homeworkQuiz);
      quizData.setNewQuizId(homeworkQuiz.getId());
    });
    return homeworkQuizzesData;
  }
}
